package com.yanchengtect.demo.progress.dao;

import com.yanchengtect.demo.progress.common.annotation.ID;
import com.yanchengtect.demo.progress.common.annotation.TableName;
import com.yanchengtect.demo.progress.utils.YCStringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.util.*;

/**
* @author 文心雕龙 Email：xuwenlong@shike8888.com
* @version 创建时间：2018年9月5日 下午4:30:24
* 类说明
*/
public class BaseDao<T> {
	
	@Autowired
	public JdbcTemplate jdbcTemplate;
	
	public final Logger log = LoggerFactory.getLogger(getClass());



	/**
	 * 根据表名和对象新增记录
	 * @param tableName 表名
	 * @param object 对象
	 * @return
	 */
	public int addOne(String tableName,T object) {
		
		Class<? extends Object> clazz = object.getClass();
		Field[] fields = clazz.getDeclaredFields();
		
		if (fields.length>0) {
			// 组织sql语句
			StringBuffer sql = new StringBuffer("insert into ").append(tableName).append("(");
			// 拼接值字符串
			StringBuffer values = new StringBuffer( );
			// 拼接字段名字符串
			StringBuffer columns = new StringBuffer();
			// 参数列表
			List<Object> args = new ArrayList<Object>();
			
			for (Field field : fields) {
				
				field.setAccessible(true);
				
				try {
					if (null!=field.get(object)) {
						columns.append(YCStringUtil.camel2Underline(field.getName())).append(",");
						values.append("?,");
						args.add(field.get(object));
					}
				} catch ( Exception e) {
					e.printStackTrace();
					log.error(e.getMessage());
				} 
			}
			
			if (columns.length()>0) {
				sql.append(columns.deleteCharAt(columns.lastIndexOf(",")))
				.append(") values (")
				.append(values.deleteCharAt(values.lastIndexOf(",")))
				.append(")");
			}
			
			// 日志打印(debug)sql语句
			log.debug(sql.toString());
			return jdbcTemplate.update(sql.toString(), args.toArray());
		}
		return 0;
	}
	

	/**
	 * 根据对象新增记录
	 * @param object 对象
	 * @return
	 */
	public int addOne(T object) {
		String clazzSimpleName = object.getClass().getSimpleName();
		return addOne(Character.toLowerCase(clazzSimpleName.charAt(0))+YCStringUtil.camel2Underline(clazzSimpleName.substring(1)),object);
	}
	
	
	
	/**
	 * 根据int类型的id查询记录
	 * @param id 
	 * @return T 记录对象
	 */
	@SuppressWarnings("unchecked")
	public T findById(int id) {
		// 获取泛型的类对象
		Class<T> tClass = (Class<T>)((ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[0];
		
		String clazzSimpleName =tClass.getSimpleName();
		
		if (tClass.isAnnotationPresent(TableName.class)) {
			clazzSimpleName = tClass.getAnnotation(TableName.class).value();
		}
		
		// 获取简单的类名(不含包名)
		return findById(Character.toLowerCase(clazzSimpleName.charAt(0))+YCStringUtil.camel2Underline(clazzSimpleName.substring(1)),id);
	}
	
	
	
	/**
	 * 根据int类型的id查询记录
	 * @param tableName 表名
	 * @param id
	 * @return T 记录对象
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public T findById(String tableName,int id) {
		// 获取泛型的类对象
		Class<T> tClass = (Class<T>)((ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[0];
		
		Field[] fields = tClass.getDeclaredFields();
		
		// 主键的名称
		String primaryName = "id";
		
		if (fields.length>0) {
			for (Field field : fields) {
				if (field.isAnnotationPresent(ID.class)) {
					primaryName = field.getAnnotation(ID.class).value();
				}
			}
		}
		
		String sql = "select * from "+tableName+" where "+primaryName+" = ?";
		log.debug(sql.toString());
		List<T> list = jdbcTemplate.query(sql, new Object[] {id},new RowMapperUtil(tClass));
		  
		  if (list.size()>0) {
			return list.get(0);
		 }else {
			 return null;
		 }
	}
	
	
	
	/**
	 * 根据对象查询列表(条件为对象非空字段)
	 * @param object 对象
	 * @return
	 */
	public List<T> queryList(T object){
		String clazzSimpleName =object.getClass().getSimpleName();
		return queryList(Character.toLowerCase(clazzSimpleName.charAt(0))+YCStringUtil.camel2Underline(clazzSimpleName.substring(1)),object);
	}
	
	
	
	/**
	 * 根据表名和对象查询列表(条件为对象非空字段)
	 * @param tableName 表名
	 * @param object 对象
	 * @return
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public List<T> queryList(String tableName,T object){
		
		Class<? extends Object> clazz = object.getClass();
		Field[] fields = clazz.getDeclaredFields();
		
		if (fields.length>0) {
			// 组织sql语句
			StringBuffer sql = new StringBuffer("select * from ").append(tableName).append(" where 1=1 ");
			
			// 参数列表
			List<Object> args = new ArrayList<Object>();
			
			for (Field field : fields) {
				
				field.setAccessible(true);
				
				try {
					if (null!=field.get(object)) {
						sql.append(" and ").append(YCStringUtil.camel2Underline(field.getName())).append("= ?");
						args.add(field.get(object));
					}
				} catch (Exception e) {
					e.printStackTrace();
					// 日志打印
					log.error(e.getMessage());
				}
			}
			// 日志打印
			log.debug(sql.toString());
			return jdbcTemplate.query(sql.toString(), args.toArray(),new RowMapperUtil(clazz));
		}
		return null;
	}


	/**
	 * 更新对象信息
	 * @param tableName
	 * @param object
	 * @param conditions
	 * @return
	 */
	public int update(String tableName,T object,Map<String, Object> conditions){
		
		Class<? extends Object> clazz = object.getClass();
		Field[] fields = clazz.getDeclaredFields();
		
		if (fields.length>0) {
			// 组织sql语句
			StringBuffer sql = new StringBuffer();
			StringBuffer set = new StringBuffer();

			// 参数列表
			List<Object> args = new ArrayList<Object>();
			
			for (Field field : fields) {
				
				field.setAccessible(true);
				
				try {
					if (null!=field.get(object)) {
						if (set.length()==0) {
							set.append(" set ").append(YCStringUtil.camel2Underline(field.getName())).append("= ? ");
						}else {
							set.append(",").append(YCStringUtil.camel2Underline(field.getName())).append("= ? ");
						}
						
						args.add(field.get(object));
					}
				} catch (Exception e) {
					e.printStackTrace();
					// 日志打印
					log.error(e.getMessage());
				}  
			}
			
			
			if (set.length()>0) {
				sql.append("update ").append(tableName).append(set);
				// where 条件的封装
				if (conditions!=null) {
					Set<String> keySet = conditions.keySet();
					if (keySet.size()>0) {
						StringBuffer wheres = new StringBuffer();
						for (String key : keySet) {
							
							if (wheres.length()==0) {
								wheres.append(" where ");
							}else {
								wheres.append(" and ");
							}
							
							wheres.append(key).append("= ? "); 
							args.add(conditions.get(key));
						}
						
						sql.append(wheres);
					}
				}
			}
			
			// 日志打印
			log.debug(sql.toString());
			return jdbcTemplate.update(sql.toString(), args.toArray());
		}
		return 0;
	}
	
	
	/**
	 * 根据对象更新记录
	 * @param object 待更新的对象
	 * @return
	 */
	public int updateOne(T object) {
		String clazzSimpleName =object.getClass().getSimpleName();
		Map<String, Object> conditions = new HashMap<String, Object>();
		return update(Character.toLowerCase(clazzSimpleName.charAt(0))+YCStringUtil.camel2Underline(clazzSimpleName.substring(1)),object,conditions);
	}
}
